package com.justgame.project.base.config;


import com.justgame.project.base.auth.Auth2Realm;
import com.justgame.project.cloud.common.constant.Const;
import com.justgame.project.base.filter.Auth2Filter;
import com.justgame.project.cloud.common.util.AppContextUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

// 实现ApplicationContextAware是为了获取上下文，否则获取不到Bean
// 暂未找到@Value及@Autowired无效的原因

/**
 * Shiro安全配置
 */
@DependsOn("appContextUtils")
@Configuration
public class ShiroConfig{


    @Bean("securityManager")
    public DefaultWebSecurityManager securityManager(Auth2Realm realm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        /* 配置校验机制 */
        manager.setRealm(realm);
        /* 配置身份权限缓存管理器 */
        manager.setCacheManager(redisCacheManager());
        /* 配置 ‘记住我’ 管理器 */
        manager.setRememberMeManager(null);
        return manager;
    }

    /* 配置RedisManager */
    @Bean
    public RedisManager redisManager() {
        RedisManager manager = new RedisManager();
        RedisProperties properties = AppContextUtils.getBean(RedisProperties.class);
        manager.setHost(properties.getHost() + ":" + properties.getPort());
        manager.setPassword(StringUtils.isBlank(properties.getPassword()) ? null : properties.getPassword());
        manager.setDatabase(properties.getDatabase());
        return manager;
    }

    /**
     * shiro-redis 插件缓存用户权限
     *
     * @return
     */
    @Bean
    public RedisCacheManager redisCacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        redisCacheManager.setExpire(Const.TIME_TIMEOUT_TOKEN.intValue());
        redisCacheManager.setPrincipalIdFieldName("id");
        return redisCacheManager;
    }


    @Bean
    public FilterRegistrationBean shiroFilterRegistrationBean() {
        FilterRegistrationBean frb = new FilterRegistrationBean();
        frb.setFilter(new DelegatingFilterProxy("shiroFilter"));
        frb.addInitParameter("targetFilterLifecycle", "true");
        frb.setEnabled(true);
        frb.setOrder(Integer.MAX_VALUE - 1);
        return frb;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        filterFactory.setSecurityManager(securityManager);
        //   引入自己的Filter处理逻辑
        Map<String, Filter> filters = new HashMap<>();
        filters.put("auth", new Auth2Filter());
        filterFactory.setFilters(filters);

        //    建立URL与访问权限的映射
        Map<String, String> filter = new HashMap<>();

        /* 文件信息 */
        filter.put("/sys/f-info/**", "auth");
        /* 退出登录 */
        filter.put("/sys/logout","auth");
        /* 文件上传 */
        filter.put("/user/uploadFile", "auth");
        filter.put("/system/upload", "auth");

        /* 管理员API */
        filter.put("/admin/**", "auth");

        /* 用户更新游戏信息 */
        filter.put("/just/game-info/update", "auth");
        filter.put("/online-info/update","auth");
        //filter.put("/common/email/send-validation","auth");
        filter.put("/art/page/usr/**", "auth");
        filter.put("/dict/save","auth");
        filter.put("/dict/update","auth");
        filter.put("/sys/station-order/**","auth");

        filter.put("/sys/f-info/sys/f-info/real-delete","anon");
        filter.put("/**", "anon");
        filterFactory.setFilterChainDefinitionMap(filter);


        //     没有权限
        filterFactory.setUnauthorizedUrl("/sys/common/403");
        //     登陆URL
        filterFactory.setLoginUrl("/sys/login");
        return filterFactory;
    }


    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 开启权限授权注解支持
     * 不配置会出现不识别 @RequiresRoles 注解的情况
     *
     * @return
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
